今天就分享 3 個 Rust 記憶體招式,copy_from_slice、split_at_mut、chunks_exact_mut。
copy_from_slice手上兩塊等長的 slice,要把 A 複到 B,不用自己寫 for 迴圈。用標準庫已經幫你做過 bounds 檢查的 copy_from_slice。
fn stamp_prefix(dst: &mut [u8], prefix: &[u8]) {
assert!(prefix.len() <= dst.len());
let (head, _) = dst.split_at_mut(prefix.len());
head.copy_from_slice(prefix);
}
長度不對會直接 panic 喔
fn overwrite(dst: &mut [u8], src: &[u8]) {
dst.copy_from_slice(src); // 需要等長,否則 panic
}
split_at_mutRust 不允許同一個切片同時有兩個 &mut,但不重疊的兩段就沒問題。split_at_mut 幫你安全地把一塊切成兩塊。
fn fill_head_tail(buf: &mut [u8]) {
let n = buf.len() / 2;
let (head, tail) = buf.split_at_mut(n); // head 和 tail 互不重疊
// 同時操作兩塊
head.fill(0xAA);
tail.fill(0x55);
}
你想「邊讀 A、邊把結果寫到 B」,但 A 和 B 其實在同一塊大陣列裡不同區段,split_at_mut 就是安全首選。
chunks_exact_mut很多資料其實是「固定欄位長度」:例如 16-byte 的 UUID、20-byte 的 header… 與其手寫索引,不如讓切片自己吐出一塊一塊的 view。
fn xor_each_block_16(buf: &mut [u8], key: [u8; 16]) {
for block in buf.chunks_exact_mut(16) {
for (b, k) in block.iter_mut().zip(&key) {
*b ^= *k;
}
}
// 若長度不是 16 的倍數,剩下的在 remainder 處理
let rem = buf.chunks_exact_mut(16).into_remainder();
for (b, k) in rem.iter_mut().zip(&key) {
*b ^= *k;
}
}
chunks_exact_mut(4) 讓你自然地以「一筆」為單位處理,不用手算索引、也不會越界。
Vec 的配置姿勢很多人會寫 Vec::with_capacity(len) 然後想「直接當作已填滿」使用,不行。安全作法用 resize 或建一個全零的:
fn new_zeroed(len: usize) -> Vec<u8> {
vec![0u8; len] // 配好 + 寫零(最安全)
// 或者:
// let mut v = Vec::with_capacity(len);
// v.resize(len, 0);
// v
}
set_len 是 unsafe,除非你真的保證之後每個位元組都會被正確寫入,否則不要用。
寫作業寫到兩眼一黑,為什麼作業這麼多啊?而且快考試了書還唸不完,我真的好爛:(